/**
 * Copyright (C) 2013 DaiKit.com - daikit4gxt module (admin@daikit.com)
 *
 *         Project home : http://code.daikit.com/daikit4gxt
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.daikit.daikit4gxt.client.ui.popup;

import com.daikit.commons.shared.exception.DkUnsupportedMethodException;
import com.daikit.daikit4gxt.client.DkBaseMain;
import com.daikit.daikit4gxt.client.constants.DkErrorCodes;
import com.daikit.daikit4gxt.client.editor.DkClearValidationVisitor;
import com.daikit.daikit4gxt.client.editor.DkPreFlushVisitor;
import com.daikit.daikit4gxt.client.editor.DkSimpleBeanEditorDriver;
import com.google.gwt.editor.client.Editor;


/**
 * A local edition popup.
 *
 * @author tcaselli
 * @version $Revision$ Last modifier: $Author$ Last commit: $Date$
 * @param <BEANTYPE>
 *           the bean type
 * @param <EDITORTYPE>
 *           the editor type for editing BEANTYPE
 */
public abstract class DkLocalFormPopup<BEANTYPE, EDITORTYPE extends Editor<BEANTYPE>> extends DkFormDialog
{

	protected String labelCorrectErrorsTitle = DkBaseMain.i18n().error_validation_popup_correct_fields_before_save_title();
	protected String labelCorrectErrorsMessage = DkBaseMain.i18n().error_validation_popup_correct_fields_before_save_message();

	@SuppressWarnings("rawtypes")
	private DkSimpleBeanEditorDriver driver;

	private DkLocalFormPopupCallback<BEANTYPE> callback;
	private BEANTYPE editedModel;
	private final EDITORTYPE editor;

	/**
	 * Constructor
	 *
	 * @param editor
	 *           the editor of type EDITORTYPE
	 */
	public DkLocalFormPopup(final EDITORTYPE editor)
	{
		super(false, 1, DisplayableButton.CANCEL, DisplayableButton.OK, DisplayableButton.RESET);
		this.editor = editor;
		getSetupDriver().initialize(editor);

	}

	/**
	 * Create (the first time) and get the driver.
	 *
	 * @return the edition driver
	 */
	@SuppressWarnings("unchecked")
	protected DkSimpleBeanEditorDriver<BEANTYPE, EDITORTYPE> getSetupDriver()
	{
		if (driver == null)
		{
			driver = getDriver();
			driver.initialize(editor);
		}
		return driver;
	}

	/**
	 * For more information about GWT Editor :<br>
	 * <a href="https://developers.google.com/web-toolkit/doc/latest/DevGuideUiEditors">
	 * https://developers.google.com/web-toolkit/doc/latest/DevGuideUiEditors</a>
	 *
	 * @return the editor driver
	 */
	protected abstract DkSimpleBeanEditorDriver<BEANTYPE, EDITORTYPE> getDriver();

	/**
	 * Use {@link #show(DkLocalFormPopupCallback)} instead.
	 */
	@Deprecated
	@Override
	public void show()
	{
		throw new DkUnsupportedMethodException(DkErrorCodes.DK4GXT00002, "Use show(MyLocalFormPopupCallback) instead");
	}

	/**
	 * Show the popup.
	 *
	 * @param callback
	 */
	public void show(final DkLocalFormPopupCallback<BEANTYPE> callback)
	{
		this.callback = callback;
		getSetupDriver().edit(null);
		editedModel = createBeanInstance();
		getSetupDriver().accept(new DkClearValidationVisitor());
		getSetupDriver().edit(editedModel);
		super.show();
	}

	protected abstract BEANTYPE createBeanInstance();

	@Override
	protected void onButtonOkClicked()
	{
		super.onButtonOkClicked();
		onButtonSaveOrOkClicked();
	}

	@Override
	protected void onButtonResetClicked()
	{
		getSetupDriver().accept(new DkClearValidationVisitor());
		getSetupDriver().edit(editedModel);
		invalidateUi();
	}

	@Override
	protected void onButtonSaveClicked()
	{
		super.onButtonSaveClicked();
		onButtonSaveOrOkClicked();
	}

	protected void onButtonSaveOrOkClicked()
	{
		driver.accept(new DkPreFlushVisitor(true));
		final BEANTYPE updatedModel = getSetupDriver().flush();
		if (driver.hasErrors())
		{
			DkMessageBox.alert(labelCorrectErrorsTitle, labelCorrectErrorsMessage);
		}
		else
		{
			hide();
			if (callback != null)
			{
				callback.onButtonOkClicked(updatedModel);
			}
		}
	}

	/**
	 * @return the editedModel
	 */
	public BEANTYPE getEditedModel()
	{
		return editedModel;
	}

	/**
	 * @return the editor
	 */
	public EDITORTYPE getEditor()
	{
		return editor;
	}

}
